package com.peng.rpc.netty.util;

import com.peng.rpc.entity.RpcRequest;
import com.peng.rpc.entity.RpcResponse;
import com.peng.rpc.enumeration.PackageType;
import com.peng.rpc.enumeration.RpcError;
import com.peng.rpc.exception.RpcException;
import com.peng.rpc.serializer.CommonSerializer;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ReplayingDecoder;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * +---------------+---------------+-----------------+-------------+
 * |  Magic Number |  Package Type | Serializer Type | Data Length |
 * |    4 bytes    |    4 bytes    |     4 bytes     |   4 bytes   |
 * +---------------+---------------+-----------------+-------------+
 * |                          Data Bytes                           |
 * |                   Length: ${Data Length}                      |
 * +---------------------------------------------------------------+
 * @author Wonderson
 * @email wpp.ds@foxmail.com
 * @date 2022/3/1 21:00
 */
@Slf4j
public class CommonDecoder extends ReplayingDecoder {

    private static final int MAGIC_NUMBER = 0xCAFEBABE;

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> res) throws Exception {
        int magicNum = in.readInt();
        if (magicNum != MAGIC_NUMBER) {
            log.error("不合法的数据包");
            throw new RpcException(RpcError.UNKNOWN_PROTOCOL);
        }

        int packageType = in.readInt();
        Class<?> packageTypeClass;
        if (packageType ==  PackageType.REQUEST_PACKAGE.getCode()) {
            packageTypeClass = RpcRequest.class;
        } else if (packageType == PackageType.RESPONSE_PACKAGE.getCode()) {
            packageTypeClass = RpcResponse.class;
        } else {
            log.error("不支持的协议包");
            throw new RpcException(RpcError.UNKNOWN_PACKAGE_TYPE);
        }

        int serializerCode = in.readInt();
        CommonSerializer serializer = CommonSerializer.getSerializerByCode(serializerCode);
        if (serializer == null) {
            log.error("不支持的序列化方式");
            throw new RpcException(RpcError.UNKNOWN_SERIALIZER);
        }

        int length = in.readInt();
        byte[] bytes = new byte[length];
        in.readBytes(bytes);
        Object object = serializer.deserialize(bytes, packageTypeClass);
        res.add(object);
    }
}
